package aspectJ;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;

import annotationI.SaferParam;
import annotationI.Trace;

public aspect Inspector {
	pointcut doPrint(long l) : execution(* hey(..)) && args(l);
	pointcut throwsSomething(): call(* *(..) throws *..*) && within(aspectJ..*);
	pointcut tryInt(int o): call(* *(..)) && within(aspectJ..*) && args(o);	
	pointcut catchException(): call(* *(..)) && within(aspectJ..*);

	before() : throwsSomething() {
		System.out.println("Exception throw here");
	}

	void around(Trace trace) : 
		execution (@annotationI.Trace * *(..)) 
				&& within(aspectJ..*) 
				&& @annotation(trace) {		 
		Signature signature =  thisJoinPoint.getSignature();
		System.out.println("[TRACE] Call -> " + signature.getName());
		System.out.println("[TRACE] Number parameters -> " + thisJoinPoint.getArgs().length);
		for(int i = 0; i < thisJoinPoint.getArgs().length; i++){
			System.out.println("[TRACE] Parameters " + i + ", value = " + thisJoinPoint.getArgs()[i]);	
		}
	}
	
	
	Object around(SaferParam safer) : 
		execution (@annotationI.SaferParam * *(..)) 
				&& within(aspectJ..*) 
				&& @annotation(safer) {		
		
		Object [] argArray = thisJoinPoint.getArgs();
		for(int i : safer.param()){		
			if(argArray.length <= i + 1) break;
			if(argArray[i - 1] == null){
				System.err.println("Param " + i + " is null");
				return null;
			}
		}
		return proceed(safer);
	}
	
	Object around() : catchException() {
		try{
			return proceed();
		}catch(Exception e){
			System.out.println("There is an error here " + e);
			return null;
		}
	}
}
